home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
fish
/
726-750
/
750
/
fontviewq
/
fontviewq.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-18
|
32KB
|
1,089 lines
/*****************************************************************************\
* $VER: FontViewQ.c 1.2 DICE/LATTICE C/SAS C/AZTEC C + AmigaOS 2.04/2.1 *
* _ *
* _ // (c)1992 by "Quarky" Dieter Temme *
* \\ // *
* :ts=4 \X/ --- Freeware --- ONLY AMIGA MAKES IT POSSIBLE *
* *
* commodity to show a character set table on the screen *
\*****************************************************************************/
#define PRGNAME "FontViewQ"
#define VERSION "1.2"
#define PRGDATE "22.9.92"
#define PRGNAMELEN 9 /* to avoid a 'strlen(const)' */
#include "amigacompq.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <exec/types.h>
#include <clib/alib_protos.h>
#include <clib/asl_protos.h>
#include <clib/commodities_protos.h>
#include <clib/diskfont_protos.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/graphics_protos.h>
#include <clib/icon_protos.h>
#include <clib/intuition_protos.h>
#include <clib/keymap_protos.h>
#include <clib/locale_protos.h>
#include <clib/utility_protos.h>
#include <devices/keymap.h>
#include <dos/dos.h>
#include <exec/libraries.h>
#include <exec/memory.h>
#include <graphics/text.h>
#include <intuition/gadgetclass.h>
#include <intuition/intuition.h>
#include <libraries/asl.h>
#include <libraries/commodities.h>
#include <libraries/gadtools.h>
#include <libraries/locale.h>
#ifdef PRAGMAS_
#include <pragmas/asl_lib.h>
#include <pragmas/exec_lib.h>
#include <pragmas/commodities_lib.h>
#include <pragmas/diskfont_lib.h>
#include <pragmas/dos_lib.h>
#include <pragmas/gadtools_lib.h>
#include <pragmas/graphics_lib.h>
#include <pragmas/icon_lib.h>
#include <pragmas/intuition_lib.h>
#include <pragmas/keymap_lib.h>
#include <pragmas/locale_lib.h>
#include <pragmas/utility_lib.h>
#endif
#ifdef LATTICE
int CXBRK(void) { return 0; } /* Disable Lattice CTRL-C handling */
int chkabort(void) { return 0; }
#endif
#ifdef AZTEC_C
void _wb_parse(void) { extern long Enable_Abort; Enable_Abort= FALSE; }
void _abort(void) {}
#endif
TEXT VersionString[]= "\0$VER: " PRGNAME " " VERSION " (" PRGDATE ")";
#define STRINGARRAY
#include "FontViewQ.h"
/*>> library bases and locale/catalog variables <<*/
extern struct Library *SysBase;
struct Library *AslBase, *CxBase, *DiskfontBase, *GadToolsBase, *GfxBase,
*IconBase, *IntuitionBase, *KeymapBase, *LocaleBase,
*UtilityBase;
struct Locale *locale;
struct Catalog *cat;
/*>> miscellaneous variables <<*/
struct NewBroker newbroker= /* newbroker structure */
{ 5, PRGNAME, "V" VERSION " (c)1992 by \"Quarky\" Dieter Temme", NULL,
NBU_UNIQUE|NBU_NOTIFY, COF_SHOW_HIDE
};
CxObj *broker; /* Commodities' broker structure */
TEXT *hotkey; /* hotkey description */
struct MsgPort *brokport; /* port for Commodities' messages */
struct FontRequester *freq; /* ASL's font requester structure */
APTR vi; /* Intuition's visual information */
struct Screen *pubscr; /* pointer to public screen's structure */
struct Window *win; /* pointer to FontViewQ's window structure */
struct Gadget *congad; /* pointer to GadTools' anchor gadget struct */
struct RastPort *rp; /* pointer to screen's rastport */
ULONG winsig; /* signal flag of window's userport */
struct TextFont *tabfont; /* actual font structures for table */
struct TextAttr tabtattr;
UWORD tabxsize; /* number of keys in a line of the table */
UWORD tabnumx; /* number of rows on the table page */
UWORD tabnumy; /* number of lines on the table page */
UWORD tablen; /* number of keys on one table page */
UWORD *tabmem; /* pointer to memory for the key labels */
UWORD tablopage; /* lowest key number on table page */
UWORD tabhipage; /* highest key number on table page */
UWORD tablochar; /* lowest key number in font */
UWORD tabhichar; /* highest key number in font */
UBYTE tabpages; /* number of pages of the table */
UBYTE tabpage; /* actual page number (0..tabpages-1) */
UBYTE current; /* current highlighted key */
/* miscellaneous definitions */
#define TAB_TOGGLE_ 0 /* for CtrlTable_() */
#define TAB_CLOSE_ 1
#define TAB_OPEN_ 2
#define TAB_NEWPAGE_ 3
#define TAB_NEWFONT_ 4
#define SFON_INIT_ 0 /* for SelectFont_() */
#define SFON_FILL_ 1
#define SFON_SELECT_ 2
#define GID_FONTSEL_ 0 /* for struct NewGadget */
#define GID_FONT_ 1
#define GID_CHAR_ 2
#define GID_DECIMAL_ 3
#define GID_STROKE_ 4
#define GID_PAGE_ 5
#define GID_HIDE_ 6
#define GID_QUIT_ 7
#define GID_ASCII_ 8
#define MOUSE_SET_ 0 /* for CtrlPointer_() */
#define MOUSE_CLR_ 1
#define MOUSE_INIT_ 2
#define MOUSE_REMOVE_ 3
struct
{ BYTE line; /* line diff to previous gadget, last is -1 */
UBYTE textnum; /* number of localized text string */
BYTE kind; /* parameter for CreateGadget (and ng_Flags),
actually BUTTON_KIND and TEXT_KIND,
negative: PLACETEXT_ABOVE */
UBYTE length; /* for TEXT_KIND: number of chars */
UWORD width; /* 0, later gets width in pixels */
UWORD fullwidth; /* 0, later gets full width in pixels */
struct Gadget *gad; /* NULL, later gets result of CreateGadget */
} gads[]=
{ { 0, MSG_FONTSEL, BUTTON_KIND, 0 },
{ 1, 0, TEXT_KIND, 31 },
{ 1, MSG_CHAR, TEXT_KIND, 1 },
{ 1, MSG_DECIMAL, TEXT_KIND, 3 },
{ 2, MSG_STROKE, TEXT_KIND, 31 },
{ 3, MSG_PAGE, SLIDER_KIND, 15 },
{ 1, MSG_HIDE, BUTTON_KIND, 0 },
{ 1, MSG_QUIT, BUTTON_KIND, 0 },
{ -1 }
};
/*==== get catalog string localized if locale.library is open ====*/
TEXT *GetCatalogStrQ_(UBYTE num)
{ if (LocaleBase) return GetCatalogStr(cat, num, AppStrings[num].as_Str);
return AppStrings[num].as_Str;
}
/*==== get character for "keyable" gagdets ====*/
WORD GetGadgetChar_(const ULONG num)
{ TEXT *s= strchr(GetCatalogStrQ_(num), '_');
return s? ToUpper(s[1]) : -1;
}
/*==== clean up all before exit ====*/
void CleanUp_(void)
{ void CtrlTable_(UBYTE action);
void CtrlPointer_(UBYTE action);
CtrlTable_(TAB_CLOSE_);
CtrlPointer_(MOUSE_REMOVE_);
if (pubscr) UnlockPubScreen(NULL, pubscr);
if (tabfont) CloseFont(tabfont);
if (freq) FreeAslRequest((APTR)freq);
if (broker) DeleteCxObjAll(broker);
if (brokport)
{ struct Message *msg;
while (msg= GetMsg(brokport)) ReplyMsg(msg);
DeleteMsgPort(brokport);
}
ArgArrayDone();
if (LocaleBase)
{ CloseCatalog(cat);
CloseLocale(locale);
CloseLibrary(LocaleBase);
}
if (AslBase) CloseLibrary(AslBase);
if (CxBase) CloseLibrary(CxBase);
if (DiskfontBase) CloseLibrary(DiskfontBase);
if (GadToolsBase) CloseLibrary(GadToolsBase);
if (GfxBase) CloseLibrary(GfxBase);
if (IconBase) CloseLibrary(IconBase);
if (IntuitionBase) CloseLibrary(IntuitionBase);
if (KeymapBase) CloseLibrary(KeymapBase);
if (UtilityBase) CloseLibrary(UtilityBase);
}
/*==== bring error text to the user ====*/
void ExitError_(TEXT *format, ...)
{ void CtrlPointer_(UBYTE action);
static struct EasyStruct easystruct=
{ sizeof(struct EasyStruct), 0, PRGNAME, NULL, NULL
};
ULONG idcmpflags;
va_list ap;
if (IntuitionBase)
{ DisplayBeep(pubscr);
va_start(ap, format);
CtrlPointer_(MOUSE_SET_);
easystruct.es_TextFormat= format;
easystruct.es_GadgetFormat= GetCatalogStrQ_(MSG_ABORT_GAD);
EasyRequestArgs(win, &easystruct, NULL, &va_arg(ap, TEXT *));
CtrlPointer_(MOUSE_CLR_);
}
exit(RETURN_FAIL);
}
void ExitMemError_(void)
{ ExitError_(GetCatalogStrQ_(MSG_NOMEMORY));
}
/*==== set or clear busy pointer ====*/
void CtrlPointer_(UBYTE action)
{ static ULONG idcmpflags;
/*>> busy mouse pointer image <<*/
static UWORD *pimage; /* mouse imagedata in chip mem */
static UWORD mouseimage[]= /* a 'simple sprite' */
{ 0, 0,
0x0400, 0x07c0, 0x0000, 0x07c0, 0x0100, 0x0380, 0x0000, 0x07e0,
0x07c0, 0x1ff8, 0x1ff0, 0x3fec, 0x3ff8, 0x7fde, 0x3ff8, 0x7fbe,
0x7ffc, 0xff7f, 0x7efc, 0xffff, 0x7ffc, 0xffff, 0x3ff8, 0x7ffe,
0x3ff8, 0x7ffe, 0x1ff0, 0x3ffc, 0x07c0, 0x1ff8, 0x0000, 0x07e0,
0, 0
};
switch (action)
{ case MOUSE_INIT_:
if (!(pimage= AllocMem(sizeof(mouseimage), MEMF_CHIP)))
ExitMemError_();
CopyMem(mouseimage, pimage, sizeof(mouseimage));
break;
case MOUSE_SET_:
if (pimage && win)
{ idcmpflags= win->IDCMPFlags;
ModifyIDCMP(win, IDCMP_MENUPICK);
SetPointer(win, pimage, 16, 16, -6, 0);
}
break;
case MOUSE_CLR_:
if (pimage && win)
{ ClearPointer(win);
if (idcmpflags) ModifyIDCMP(win, idcmpflags);
}
break;
case MOUSE_REMOVE_:
if (pimage) FreeMem(pimage, sizeof(mouseimage));
break;
}
}
/*==== open library ====*/
struct Library *OpenLibraryQ_(TEXT *str)
{ struct Library *base;
if (!(base= OpenLibrary(str, 0)))
ExitError_(GetCatalogStrQ_(MSG_NOTFOUND), str);
return base;
}
/*==== allocate memory ====*/
void *MAllocQ_(ULONG size)
{ void *ptr;
if (!(ptr= (void *)malloc(size))) ExitMemError_();
return ptr;
}
/*==== fill in text display gadgets ====*/
/*>>> necessary because GadTools don't center
the text or print more than one line!
NOTE: string has to end with '\n'! <<<*/
void SetGadgetDisplay_(struct Gadget *gad, TEXT *str)
{ UWORD x= gad->LeftEdge, y= gad->TopEdge, height= gad->Height;
UBYTE lines= 0;
TEXT *s, *index;
SetFont(win->RPort, win->WScreen->RastPort.Font);
SetDrMd(win->RPort, JAM1);
SetAPen(win->RPort, 0);
RectFill(win->RPort, x+2, y+1, x+gad->Width-4, y+height-2);
s= str; while (s= strchr(s, '\n'))
{ s++;
lines++;
}
y+= ((height+1-lines*(win->RPort->Font->tf_YSize+1))>>1)
+win->RPort->Font->tf_Baseline;
SetDrMd(win->RPort, JAM2);
SetAPen(win->RPort, 1);
s= str; while (*s)
{ index= strchr(s, '\n');
Move(win->RPort,
x+((gad->Width-TextLength(win->RPort, s, index-s))>>1), y);
Text(win->RPort, s, index-s);
s= index+1;
y+= win->RPort->Font->tf_YSize+1;
}
}
/*==== handle fonts ====*/
void SelectFont_(UBYTE action)
{ struct RastPort *rport;
if (action == SFON_INIT_)
{ rport= &pubscr->RastPort;
goto setfont;
} else if (action == SFON_SELECT_)
{ CtrlPointer_(MOUSE_SET_);
if (AslRequestTags(freq,
ASLFO_TitleText, GetCatalogStrQ_(MSG_CHOOSEFONT),
ASLFO_Window, win,
ASLFO_InitialName, tabtattr.ta_Name,
ASLFO_InitialSize, tabtattr.ta_YSize,
TAG_DONE))
{ CloseFont(tabfont);
rport= win->RPort;
rport->Font= tabfont= OpenDiskFont(&freq->fo_Attr);
setfont: tabtattr.ta_Name= rport->Font->tf_Message.mn_Node.ln_Name;
tabtattr.ta_YSize= rport->Font->tf_YSize;
tabtattr.ta_Style= rport->Font->tf_Style;
tabtattr.ta_Flags= rport->Font->tf_Flags;
if (!tabfont) tabfont= OpenDiskFont(&tabtattr);
if (tabtattr.ta_Flags&FPF_PROPORTIONAL) /* find biggest xsize */
{ UBYTE x= tabfont->tf_LoChar, n;
tabxsize= 0;
do
{ n= TextLength(rport, &x, 1);
if (n > tabxsize) tabxsize= n;
} while (x++ != tabfont->tf_HiChar);
} else
tabxsize= tabfont->tf_XSize;
}
CtrlPointer_(MOUSE_CLR_);
} else /* if (action == SFON_FILL_) */
{ TEXT s[31]= { ' ' };
strcpy(s, tabtattr.ta_Name);
sprintf(strrchr(s, '.'), "/%lu\n", tabtattr.ta_YSize);
SetGadgetDisplay_(gads[GID_FONT_].gad, s);
}
}
/*==== put description of keystroke for character into buffer ====*/
/*>>> actually function is guaranteed only for AmigaOS 2.04/2.1! <<<*/
void MapANSIChar_(UBYTE chr, TEXT buffer[256])
{ /* >> these definitions are hopefully ok in all national keymaps! << */
#define NUMDEADKEYS 5 /* a maximum of 16 is possible */
static TEXT deadkeys[NUMDEADKEYS]= /* rawkey codes of deadkeys */
{ 0x23, 0x24, 0x25, 0x26, 0x27
};
struct KeyMap *km= AskKeyMapDefault(); /* pointer to default keymap */
UBYTE qualflags; /* qualifiers SHIFT, ALT, CTRL */
UBYTE key; /* raw key number 0x00 .. 0x7f */
UBYTE dead= 0; /* number of deadkey from table */
const static BYTE mapoffsets[8][8]= /* [LoKeyMapTypes[lokey]][qualflags] */
{ /* none, S , A , SA , C, S C, AC, SAC */
{ 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, /* none */
{ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, /* S */
{ 0x00, 0xff, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff }, /* A */
{ 0x00, 0x01, 0x02, 0x03, 0xff, 0xff, 0xff, 0xff }, /* SA */
{ 0x00, 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff }, /* C */
{ 0x00, 0x01, 0xff, 0xff, 0x02, 0x03, 0xff, 0xff }, /* S C */
{ 0x00, 0xff, 0x01, 0xff, 0x02, 0xff, 0x03, 0xff }, /* AC */
{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 } /* SAC */
};
buffer[0]= '\0';
/*- get control characters using the common way -*/
if ((chr&0x7f) < ' ')
{ union
{ UWORD word;
struct
{ UBYTE code, qual;
} bytes;
} buf;
if (MapANSI(&chr, 1, &buf, 1, NULL) > 0)
{ key= buf.bytes.code;
qualflags= 0;
if (buf.bytes.qual&(IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
qualflags|= KCF_SHIFT;
if (buf.bytes.qual&(IEQUALIFIER_LALT|IEQUALIFIER_RALT))
qualflags|= KCF_ALT;
if (buf.bytes.qual&(IEQUALIFIER_CONTROL))
qualflags|= KCF_CONTROL;
goto found;
}
}
/*- find rawkey qualifier and code in keymap -*/
{ BYTE offset; /* byte offset into LoKeyMap[lokey] */
BOOL deadflag; /* FALSE: search non-dead, TRUE: dead */
UBYTE *kmtypes; /* pointer into km_??KeyMapTypes */
ULONG *kmmap; /* pointer into km_??KeyMap */
for (deadflag= FALSE; deadflag <= TRUE; deadflag++)
{ for (qualflags= KC_NOQUAL; qualflags <= KC_VANILLA; qualflags++)
{ for (key= 0; key <= 0x78; key++)
{ if (!(key&0x3f))
{ kmtypes= key&0x40?
km->km_HiKeyMapTypes : km->km_LoKeyMapTypes;
kmmap= key&0x40? km->km_HiKeyMap: km->km_LoKeyMap;
}
offset= mapoffsets[*kmtypes&KC_VANILLA][qualflags];
if (!(*kmtypes&KCF_NOP) && (offset >= 0))
{ if (*kmtypes&KCF_DEAD)
{ UBYTE *addr= (UBYTE *)*kmmap;
if (addr[offset<<1]&DPF_MOD)
{ addr+= addr[(offset<<1)|1]+deadflag;
dead= deadflag;
do
{ if (*addr == chr) goto found;
addr++;
dead++;
} while (deadflag && (dead != NUMDEADKEYS+1));
dead= 0;
} else if (((UWORD *)addr)[offset] == (UWORD)chr)
goto found;
} else if (!deadflag && !(offset&4))
{ offset= (offset&3)^3;
if (*kmtypes&KCF_STRING)
{ UBYTE *addr= (UBYTE *)*kmmap;
if ((addr[offset<<1] == 1)
&& (addr[addr[(offset<<1)|1]] == chr))
goto found;
} else if (((UBYTE *)kmmap)[offset] == chr)
goto found;
}
}
kmtypes++;
kmmap++;
}
}
}
}
return; /* not found */
found:
/*- put description into buffer -*/
{ struct InputEvent ie; /* structure for MapRawKey() */
TEXT *index; /* temporary index for highkeys */
static UBYTE highkeycodes[]=
{ 0x40, 0x48, 0x50, 0x58,
0x41, 0x49, 0x51, 0x59,
0x42, 0x52, 0x5f,
0x43, 0x4b, 0x53,
0x44, 0x4c, 0x54, 0x6e,
0x45, 0x4d, 0x55, 0x6f,
0x46, 0x4e, 0x56, 0x70,
0x47, 0x4f, 0x57, 0x71, 0
};
static TEXT *highkeytexts[]=
{ "space", "page_up", "f1", "f9",
"backspace", "page_down", "f2", "f10",
"tab", "f3", "help",
"enter", "f11", "f4",
"return", "up", "f5", "pause",
"esc", "down", "f6", "f12",
"del", "right", "f7", "home",
"insert", "left", "f8", "end"
};
static TEXT numkeycodes[]=
{ 0x0f, 0x1d, 0x1e, 0x1f, 0x2d, 0x2e, 0x2f, 0x3c,
0x3d, 0x3e, 0x3f, 0x4a, 0x5a, 0x5b, 0x5c, 0x5d,
0x5e, 0
};
ie.ie_Class= IECLASS_RAWKEY;
ie.ie_Qualifier= 0;
ie.ie_EventAddress= 0;
if (dead)
{ strcpy(buffer, "alt ,\n");
ie.ie_Code= deadkeys[dead-1];
MapRawKey(&ie, buffer+4, 1, km);
}
if (qualflags&KCF_CONTROL) strcat(buffer, "ctrl ");
if (qualflags&KCF_SHIFT) strcat(buffer, "shift ");
if (qualflags&KCF_ALT) strcat(buffer, "alt ");
if (key && (index= strchr(highkeycodes, key)))
{ strcat(buffer, highkeytexts[index-highkeycodes]);
strcat(buffer, "\n");
} else
{ if (key && strchr(numkeycodes, key)) strcat(buffer, "numericpad ");
strcat(buffer, " \n");
ie.ie_Code= key;
MapRawKey(&ie, strrchr(buffer, ' '), 1, km);
}
}
}
/*==== color gadget of current key ====*/
void ColorCurrentKey_(UBYTE which, UBYTE color)
{ UWORD x, y;
SetFont(win->RPort, tabfont);
SetDrMd(win->RPort, JAM1);
SetAPen(win->RPort, color);
x= INTERWIDTH+((which-tablopage)%tabnumx)*(tabxsize+INTERWIDTH);
y= INTERHEIGHT+1+((which-tablopage)/tabnumx)*(tabtattr.ta_YSize+6);
RectFill(win->RPort, x+2, y,
x+2+tabxsize+INTERWIDTH-5, y+tabtattr.ta_YSize+6-3);
SetAPen(win->RPort, 1);
Move(win->RPort,
x+((1+INTERWIDTH+tabxsize-TextLength(win->RPort, &which, 1))>>1),
y+3-1+tabfont->tf_Baseline);
Text(win->RPort, &which, 1);
}
/*==== show info of selected character ====*/
void OutputCharInfo_(UBYTE num)
{ TEXT s[256];
if ((current >= tablopage) && (current < tabhipage))
/* de-color old actual key gadget */
ColorCurrentKey_(current, 0);
if ((num >= tablopage) && (num < tabhipage))
{ /* set character gadget */
if ((num&0x7f) >= 0x20)
{ s[0]= num; s[1]= '\n'; s[2]= '\0';
} else
s[0]= '\0';
SetGadgetDisplay_(gads[GID_CHAR_].gad, s);
/* set decimal value gadget */
sprintf(s, "%lu\n", num);
SetGadgetDisplay_(gads[GID_DECIMAL_].gad, s);
/* set stroke gadget */
MapANSIChar_(num, s);
SetGadgetDisplay_(gads[GID_STROKE_].gad, s);
/* color new actual key gadget */
ColorCurrentKey_(current= num, 3);
} else
{ SetGadgetDisplay_(gads[GID_CHAR_].gad, "\n");
SetGadgetDisplay_(gads[GID_DECIMAL_].gad, "\n");
SetGadgetDisplay_(gads[GID_STROKE_].gad, "\n");
}
}
/*==== open or close character table ====*/
void CtrlTable_(UBYTE action)
{ static struct NewWindow newwin=
{ 0, 0, 0, 0, 0, 1,
SLIDERIDCMP|BUTTONIDCMP|IDCMP_CLOSEWINDOW
|IDCMP_VANILLAKEY|IDCMP_RAWKEY,
WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|WFLG_ACTIVATE
|WFLG_SMART_REFRESH|WFLG_NOCAREREFRESH|WFLG_GIMMEZEROZERO,
NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, PUBLICSCREEN
};
static struct TagItem texttags[]=
{ GTTX_Border, TRUE
}, moretags[]=
{ STRINGA_ExitHelp, TRUE,
GT_Underscore, (ULONG)'_',
TAG_DONE
}, pagetags[]=
{ GA_RelVerify, TRUE,
PGA_Freedom, LORIENT_HORIZ,
TAG_DONE
};
static BOOL tableopen; /* TRUE if window is open */
BYTE i; /* loop variable */
UWORD m, n; /* temporary text lengths */
TEXT *str; /* temporary string pointer */
struct NewGadget newgad; /* structure for CreateGadget() */
struct Gadget *keygad= NULL; /* pointer to first key gadget */
static UWORD fieldwidth; /* width of choice gadgets */
static UWORD fieldheight; /* height of choice gadgets */
static xsize, ysize; /* font size */
static UWORD winwidth, winheight; /* window dimensions */
if (action == TAB_TOGGLE_) action= TAB_OPEN_-tableopen;
/*- bring window to front if FontViewQ loaded again -*/
if ((action == TAB_OPEN_) && tableopen)
{ WindowToFront(win);
return;
}
/*- close window -*/
if (action == TAB_CLOSE_)
{ if (win)
{ TEXT *s= win->Title;
CloseWindow(win); win= NULL;
free(s);
}
if (tabmem)
{ free(tabmem); tabmem= NULL;
}
if (congad)
{ FreeGadgets(congad); congad= NULL;
}
if (vi)
{ FreeVisualInfo(vi); vi= NULL;
}
tableopen= FALSE;
return;
}
/*- get choice gadgets' dimensions or remove gadgets from window -*/
if (!tableopen)
{ UWORD u; /* temporary underscore width */
/* lock default public screen and get visual information */
pubscr= LockPubScreen(NULL);
if (!tabfont) SelectFont_(SFON_INIT_);
rp= &pubscr->RastPort;
if (!(vi= GetVisualInfo(pubscr, TAG_DONE)))
exitnowin: ExitError_(GetCatalogStrQ_(MSG_NOWINDOW));
/* find biggest xsize of font, set xsize and ysize */
if (rp->Font->tf_Flags&FPF_PROPORTIONAL)
{ UBYTE n, x= rp->Font->tf_LoChar;
if (32 > x) x= 32;
x--;
xsize= 0;
do
{ x++;
n= TextLength(rp, &x, 1);
if (n > xsize) xsize= n;
} while ((x < 126) && (x != rp->Font->tf_HiChar));
xsize= (xsize<<1)/3;
} else
xsize= rp->Font->tf_XSize;
ysize= rp->Font->tf_YSize;
/* handle all widths correctly */
u= TextLength(rp, "_", 1);
fieldwidth= 0;
fieldheight= 2*INTERHEIGHT+6+ysize;
i= -1; while (gads[++i].line != -1)
{ fieldheight+= gads[i].line*(INTERHEIGHT+6+ysize);
str= gads[i].textnum? GetCatalogStrQ_(gads[i].textnum) : "";
m= TextLength(rp, str, strlen(str));
switch (gads[i].kind)
{ case SLIDER_KIND:
n= xsize*gads[i].length;
m+= INTERWIDTH+n;
break;
case TEXT_KIND:
n= xsize*(gads[i].length+1)+3*INTERWIDTH;
if (i == GID_STROKE_)
{ if (n > m) m= n;
} else
{ if (m) m+= INTERWIDTH;
m+= n;
}
break;
case BUTTON_KIND:
m= n= 3*INTERWIDTH+m;
if (strchr(str, '_')) n-= u;
}
gads[i].width= n;
gads[i].fullwidth= m;
if (m > fieldwidth) fieldwidth= m;
}
} else
{ CtrlPointer_(MOUSE_SET_);
if (action == TAB_NEWFONT_)
{ RemoveGList(win, congad, -1);
FreeGadgets(congad); congad= NULL;
SetDrMd(win->RPort, JAM1);
SetAPen(win->RPort, 0);
RectFill(win->RPort, 0, 0, win->GZZWidth-1, win->GZZHeight-1);
} else /* if (action == TAB_NEWPAGE_) */
{ RemoveGList(win, gads[GID_QUIT_].gad->NextGadget, -1);
FreeGadgets(gads[GID_QUIT_].gad->NextGadget);
gads[GID_QUIT_].gad->NextGadget= NULL;
SetDrMd(win->RPort, JAM1);
SetAPen(win->RPort, 0);
RectFill(win->RPort, INTERWIDTH, 0,
INTERWIDTH+tabnumx*(INTERWIDTH+tabxsize)-1, win->GZZHeight-1);
}
}
/*- calculate new window dimensions -*/
winwidth= fieldwidth+3*INTERWIDTH;
/*- calculate dimensions of table and create choice gadgets -*/
if (action != TAB_NEWPAGE_)
{ /* calculate dimensions of table */
{ UWORD scrheight;
if (action == TAB_OPEN_)
{ win= OpenWindowTags(NULL,
WA_Width, 1,
WA_Height, 1);
}
scrheight= win->WScreen->Height-win->BorderTop+win->BorderBottom
-2*INTERHEIGHT;
if (action == TAB_OPEN_)
{ CloseWindow(win);
win= NULL;
}
tabnumy= scrheight/(tabtattr.ta_YSize+INTERHEIGHT);
}
tabnumx= 1; m= ~0;
n= ((pubscr? pubscr : win->WScreen)->Width-winwidth-2*INTERWIDTH)
/(tabxsize+INTERWIDTH);
while (n > (tabnumx<<1)) { tabnumx<<= 1; m<<= 1; }
tablochar= tabfont->tf_LoChar&m;
tabhichar= (tabfont->tf_HiChar+tabnumx-1)&m;
m= tabnumx*tabnumy; n= tabhichar-tablochar;
tabpages= (m-n < 0)? (n+m-1)/m : 1;
n= (n+tabpages-1)/tabpages;
while ((((tabnumx*tabnumy)>>1) > n) && (tabnumx > 1)) tabnumx>>= 1;
tabnumy= ((tabhichar-tablochar+tabpages-1)
/tabpages+tabnumx-1)/tabnumx;
tablen= tabnumx*tabnumy;
if (tabmem) free(tabmem);
tabpage= 0;
tabmem= (UWORD *)MAllocQ_((tabhichar-tablochar)<<1);
if (!tabmem) ExitMemError_();
{ UWORD j;
for (j= tablochar; j != tabhichar; j++)
tabmem[j-tablochar]= j<<8;
}
winwidth+= tabnumx*(INTERWIDTH+tabxsize);
/* bring gadgets to screen */
CreateContext(&congad);
newgad.ng_TextAttr= (tableopen? win->WScreen : pubscr)->Font;
newgad.ng_VisualInfo= vi;
newgad.ng_TopEdge= INTERHEIGHT;
newgad.ng_GadgetID= 0;
i= -1; while ((n= gads[++i].line) != -1)
{ while (n-- > 0)
newgad.ng_TopEdge+= ysize+6+INTERHEIGHT;
newgad.ng_Flags=
(gads[i].kind == BUTTON_KIND)? PLACETEXT_IN :
(i == GID_STROKE_)? PLACETEXT_ABOVE : PLACETEXT_LEFT;
newgad.ng_Height= (i == GID_PAGE_)? ysize : 6+ysize;
if (i == GID_STROKE_) newgad.ng_Height<<= 1;
newgad.ng_Width= gads[i].width;
newgad.ng_LeftEdge= winwidth-INTERWIDTH
-((fieldwidth-gads[i].fullwidth)>>1)-gads[i].width;
newgad.ng_GadgetText= gads[i].textnum?
GetCatalogStrQ_(gads[i].textnum) : NULL;
gads[i].gad= CreateGadgetA((ULONG)gads[i].kind,
i? gads[i-1].gad : congad, &newgad,
(gads[i].kind == BUTTON_KIND)? moretags :
(gads[i].kind == SLIDER_KIND)? pagetags : texttags);
newgad.ng_GadgetID++;
}
if (!gads[GID_QUIT_].gad) goto exitnowin;
}
/*- create character set gadgets -*/
{ UWORD j;
newgad.ng_VisualInfo= vi;
newgad.ng_TextAttr= &tabtattr;
newgad.ng_Width= tabxsize+INTERWIDTH;
newgad.ng_Height= tabtattr.ta_YSize+6;
newgad.ng_TopEdge= INTERHEIGHT-newgad.ng_Height;
newgad.ng_GadgetID= GID_ASCII_+tabpage*tablen;
tablopage= tablochar+tablen*tabpage;
tabhipage= tablochar+tablen*(tabpage+1);
if (tabhipage > tabhichar) tabhipage= tabhichar;
{ struct Gadget *kgad= CreateContext(&keygad);
UWORD *tmptr= tabmem+tablopage-tablochar;
for (j= tablopage; j != tabhipage; j++)
{ if (!(j%tabnumx))
{ newgad.ng_LeftEdge= INTERWIDTH;
newgad.ng_TopEdge+= newgad.ng_Height;
} else
newgad.ng_LeftEdge+= newgad.ng_Width;
newgad.ng_GadgetText= (TEXT *)tmptr++;
kgad= CreateGadgetA(BUTTON_KIND, kgad, &newgad, NULL);
newgad.ng_GadgetID++;
}
if (!kgad) goto goexitnw;
}
winheight= fieldheight;
if ((j= newgad.ng_TopEdge+newgad.ng_Height+INTERHEIGHT)
> winheight) winheight= j;
}
/*- open or resize window -*/
if (!tableopen)
{ TEXT *l, *s, q[]= "%s: Hot Key = <%s>";
struct Catalog *ccat;
if (LocaleBase)
ccat= OpenCatalogA(locale, "sys/commodities.catalog", NULL);
l= LocaleBase? GetCatalogStr(ccat, 1, q) : q;
s= MAllocQ_(PRGNAMELEN+1+strlen(l)+strlen(hotkey));
sprintf(s, l, PRGNAME, hotkey);
if (LocaleBase) CloseCatalog(ccat);
if (!(win= OpenWindowTags(&newwin,
WA_Title, s,
WA_InnerWidth, winwidth,
WA_InnerHeight, winheight,
TAG_DONE)))
goexitnw:
{ FreeGadgets(keygad);
goto exitnowin;
}
winsig= 1<<win->UserPort->mp_SigBit;
} else if (action == TAB_NEWFONT_)
{ WORD y= win->WScreen->Height-win->TopEdge-winheight
-win->BorderTop-win->BorderBottom;
WORD x= win->WScreen->Width-win->LeftEdge-winwidth
-win->BorderLeft-win->BorderRight;
MoveWindow(win, (x > 0)? 0 : x, (y > 0)? 0 : y);
SizeWindow(win,
winwidth-(win->GZZWidth), winheight-(win->GZZHeight));
}
/*- unlock public default screen -*/
if (pubscr)
{ UnlockPubScreen(NULL, pubscr); pubscr= NULL;
}
/*- add gadget list to window -*/
if (action != TAB_NEWPAGE_) AddGList(win, congad, ~0, -1, NULL);
AddGList(win, keygad, ~0, -1, NULL);
RefreshGList(congad, win, NULL, -1);
GT_RefreshWindow(win, NULL);
GT_SetGadgetAttrs(gads[GID_PAGE_].gad, win, NULL,
GTSL_Max, tabpages-1,
TAG_DONE);
tableopen= TRUE;
OutputCharInfo_(current);
SelectFont_(SFON_FILL_);
CtrlPointer_(MOUSE_CLR_);
}
int main(int argc, TEXT *argv[])
{ ULONG cxsig; /* signal flag of commodities' port */
ULONG sigrcvd; /* signal flags received from Wait() */
BOOL end= FALSE; /* TRUE if program is to exit */
BYTE i; /* temporary variable */
atexit(CleanUp_);
/*- only allow AmigaOS >= 2.04 -*/
if (SysBase->lib_Version < 37)
{ BPTR file;
file= argc? Output() : Open("CON:0/0/350/30/" PRGNAME, MODE_NEWFILE);
Write(file, "Sorry, you'll need at least AmigaOS 2.04!\n", 42);
Delay(100);
Close(file);
return RETURN_FAIL;
}
/*- open libraries -*/
IntuitionBase= OpenLibraryQ_("intuition.library");
if (LocaleBase= OpenLibrary("locale.library", 0))
{ locale= OpenLocale(NULL);
cat= OpenCatalogA(locale, PRGNAME ".catalog", NULL);
}
AslBase= OpenLibraryQ_("asl.library");
CxBase= OpenLibraryQ_("commodities.library");
DiskfontBase= OpenLibraryQ_("diskfont.library");
GadToolsBase= OpenLibraryQ_("gadtools.library");
GfxBase= OpenLibraryQ_("graphics.library");
IconBase= OpenLibraryQ_("icon.library");
KeymapBase= OpenLibraryQ_("keymap.library");
UtilityBase= OpenLibraryQ_("utility.library");
/*- process arguments or tool types -*/
argv= ArgArrayInit(argc, argv);
newbroker.nb_Pri= (BYTE)ArgInt(argv, "CX_PRIORITY", 0);
i= !Stricmp(ArgString(argv, "CX_POPUP", "TRUE"), "TRUE");
hotkey= ArgString(argv, "CX_POPKEY", "ctrl alt f");
/*- initialize as commodity with hotkey -*/
newbroker.nb_Descr= GetCatalogStrQ_(MSG_CXDESCR);
if (!(brokport= newbroker.nb_Port= CreateMsgPort())) ExitMemError_();
cxsig= 1<<brokport->mp_SigBit;
{ CxObj *filter;
LONG error;
if (!(broker= CxBroker(&newbroker, &error)) || error
|| !(filter= HotKey(hotkey, brokport, 0))
|| (AttachCxObj(broker, filter), CxObjError(filter)))
if (error != CBERR_DUP)
ExitError_(GetCatalogStrQ_(MSG_INITFAIL));
else
return RETURN_OK;
}
ActivateCxObj(broker, TRUE);
/*- allocate font requester structure -*/
if (!(freq= (struct FontRequest *)AllocAslRequestTags(ASL_FontRequest,
TAG_DONE))) ExitMemError_();
/*- allocate chip mem for busy mouse pointer -*/
CtrlPointer_(MOUSE_INIT_);
/*- eventually open window now -*/
current= 'Q';
if (i) CtrlTable_(TAB_OPEN_);
/*- big message loop -*/
while (!end)
{ sigrcvd= Wait(SIGBREAKF_CTRL_C|cxsig|winsig);
if (sigrcvd&SIGBREAKF_CTRL_C) end= TRUE;
if (sigrcvd&winsig) /* table loop */
{ struct IntuiMessage *imsg;
BOOL pageflag= FALSE;
while (pageflag || win)
{ BOOL closeflag= FALSE;
BYTE i;
/* get new message from GadTools */
imsg= GT_GetIMsg(win->UserPort);
if (pageflag && (!imsg || ((imsg->Class != IDCMP_GADGETUP)
|| (imsg->Code != GID_PAGE_))))
{ CtrlTable_(TAB_NEWPAGE_);
pageflag= FALSE;
}
if (!imsg) break;
/* process Intuition message */
switch (imsg->Class)
{ case IDCMP_GADGETUP:
i= ((struct Gadget *)imsg->IAddress)->GadgetID;
select: switch (i)
{ case GID_FONTSEL_:
SelectFont_(SFON_SELECT_);
CtrlTable_(TAB_NEWFONT_);
break;
case GID_HIDE_:
goto close;
case GID_QUIT_:
end= TRUE;
break;
case GID_PAGE_:
if (imsg->Code != tabpage)
{ tabpage= imsg->Code;
pageflag= TRUE;
}
break;
default:
OutputCharInfo_((UBYTE)i-GID_ASCII_+tablochar);
break;
}
break;
case IDCMP_VANILLAKEY:
{ WORD c= ToUpper(imsg->Code);
while (gads[++i].line != -1)
if (c == GetGadgetChar_(gads[i].textnum))
goto select;
c= imsg->Qualifier;
if ((c&(IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
&& (c&IEQUALIFIER_NUMERICPAD))
switch (imsg->Code)
{ case '1': goto raw_end; /* end */
case '3': goto raw_down; /* page down */
case '7': goto raw_home; /* home */
case '9': goto raw_up; /* page up */
}
break;
}
case IDCMP_RAWKEY:
switch (imsg->Code) /*>> from OS 2.1 and up! <<*/
{ case 0x48: /* page up */
raw_up: if (!tabpage) break;
tabpage--;
goto newpage;
case 0x49: /* page down */
raw_down: if (tabpage == tabpages-1) break;
tabpage++;
goto newpage;
case 0x70: /* home */
raw_home: if (!tabpage) break;
tabpage= 0;
goto newpage;
case 0x71: /* end */
raw_end: if (tabpage == tabpages-1) break;
tabpage= tabpages-1;
newpage: GT_SetGadgetAttrs(gads[GID_PAGE_].gad,
win, NULL,
GTSL_Level, tabpage,
TAG_DONE);
CtrlTable_(TAB_NEWPAGE_);
break;
}
break;
case IDCMP_CLOSEWINDOW:
close: closeflag= TRUE;
break;
}
/* reply message and eventually close window */
GT_ReplyIMsg(imsg);
if (closeflag)
{ while (imsg= GT_GetIMsg(win->UserPort)) GT_ReplyIMsg(imsg);
CtrlTable_(TAB_CLOSE_);
}
}
}
if (sigrcvd&cxsig) /* commodity loop */
{ CxMsg *cxmsg;
while (cxmsg= (CxMsg *)GetMsg(brokport))
{ switch (CxMsgType(cxmsg))
{ case CXM_IEVENT:
CtrlTable_(TAB_TOGGLE_);
break;
case CXM_COMMAND:
switch (i= (BYTE)CxMsgID(cxmsg))
{ case CXCMD_DISABLE:
case CXCMD_ENABLE:
ActivateCxObj(broker, i == CXCMD_ENABLE);
break;
case CXCMD_KILL:
end= TRUE;
break;
case CXCMD_APPEAR:
case CXCMD_UNIQUE:
case CXCMD_DISAPPEAR:
CtrlTable_((i == CXCMD_DISAPPEAR)?
TAB_CLOSE_ : TAB_OPEN_);
break;
}
}
ReplyMsg((struct Message *)cxmsg);
}
}
}
return RETURN_OK;
}
#ifdef _DCC
int wbmain(struct WBStartup *wbstart)
{ return main(0, (TEXT **)wbstart);
}
#endif